#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>

#include <linux/delay.h>


#define GPIO_PIN    112
int irq_num;


struct work_struct test_workqueue;



// 中断上文
irqreturn_t test_irq_handler(int irq, void *args)
{
    printk(KERN_EMERG "This is irq_interrupt\r\n");
    // 调度中断下文
    schedule_work(&test_workqueue);


    return IRQ_RETVAL(IRQ_HANDLED);
}

// 中断下文，工作处理函数
void work_cb(struct work_struct *work)
{
    msleep(1000);
    printk(KERN_EMERG "this is work cb\n");

}


static int __init gpio_irq_init(void)
{
    int ret;
    printk(KERN_EMERG "init gpio interrupt driver\r\n");

    // 获取引脚中断号
    irq_num = gpio_to_irq(GPIO_PIN);
    printk(KERN_EMERG "gpio (%d) mapped to IRQ (%d)\r\n", GPIO_PIN, irq_num);

    // 请求中断
    ret = request_irq(irq_num, test_irq_handler, IRQF_TRIGGER_RISING, "test", NULL);
    if (ret < 0)
    {
        printk(KERN_EMERG "request_irq error\r\n");
    }

    // 初始化工作项
    INIT_WORK(&test_workqueue, work_cb);


    return 0;
}


static void __exit gpio_irq_exit(void)
{

    // 释放中断号
    free_irq(irq_num, NULL);
    printk(KERN_EMERG "module exit\r\n");
}


module_init(gpio_irq_init);
module_exit(gpio_irq_exit);

MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Treasure1029");